package com.pig4cloud.pig.admin.controller;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import com.pig4cloud.pig.admin.api.entity.*;
import com.pig4cloud.pig.admin.emqx.dto.CoapClientDto;
import com.pig4cloud.pig.admin.emqx.dto.EmqxClientQueryDto;
import com.pig4cloud.pig.admin.emqx.openapi.EmqxFeignClient;
import com.pig4cloud.pig.admin.emqx.vo.EmqxDataVo;
import com.pig4cloud.pig.admin.emqx.vo.MqttClientStats;
import com.pig4cloud.pig.admin.mapper.PrDeviceMapper;
import com.pig4cloud.pig.admin.mq.MqttMessageSender;
import com.pig4cloud.pig.admin.service.PrDeviceService;
import com.pig4cloud.pig.admin.service.PrRfidService;
import com.pig4cloud.pig.admin.service.PrUserRfidInfoService;
import com.pig4cloud.pig.admin.service.PrUserService;
import com.pig4cloud.pig.common.core.util.R;
import com.pig4cloud.pig.common.log.annotation.SysLog;
import com.pig4cloud.plugin.excel.annotation.RequestExcel;
import com.pig4cloud.plugin.excel.annotation.ResponseExcel;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.jetbrains.annotations.NotNull;
import org.springdoc.api.annotations.ParameterObject;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpHeaders;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.sql.SQLIntegrityConstraintViolationException;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 设备管理
 *
 * @author pig
 * @date 2025-06-04 00:19:36
 */
@RestController
@RequiredArgsConstructor
@RequestMapping("/prDevice" )
@Tag(description = "prDevice" , name = "设备管理管理" )
@SecurityRequirement(name = HttpHeaders.AUTHORIZATION)
public class PrDeviceController {

    private final  PrDeviceService prDeviceService;
	private final PrDeviceMapper prDeviceMapper;

	@Value("${spring.mqtt.devTopic}")
	private String devTopic;
	@Resource
	private EmqxFeignClient emqFeignClient;
    /**
     * 分页查询
     * @param page 分页对象
     * @param prDevice 设备管理
     * @return
     */
    @Operation(summary = "分页查询" , description = "分页查询" )
    @GetMapping("/page" )
    @PreAuthorize("@pms.hasPermission('admin_prDevice_view')" )
    public R getPrDevicePage(@ParameterObject Page page, @ParameterObject PrDeviceEntity prDevice) {
		//在线的mq连接
		EmqxClientQueryDto emqxClientQueryDto = new EmqxClientQueryDto();
		EmqxDataVo<MqttClientStats> mqttClientStats = emqFeignClient.getMqttClientStats(emqxClientQueryDto);
		List<String> clientIdList = mqttClientStats.getData().stream().filter(MqttClientStats::getConnected).map(MqttClientStats::getClientid).collect(Collectors.toList());


		MPJLambdaWrapper<PrDeviceEntity> wrapper = new MPJLambdaWrapper<PrDeviceEntity>();
		wrapper.eq(StrUtil.isNotBlank(prDevice.getName()),PrDeviceEntity::getName,prDevice.getName());
		wrapper.eq(StrUtil.isNotBlank(prDevice.getArea()),PrDeviceEntity::getArea,prDevice.getArea());
		wrapper.eq(StrUtil.isNotBlank(prDevice.getDeptName()),PrDeviceEntity::getDeptName,prDevice.getDeptName());
		wrapper.eq(StrUtil.isNotBlank(prDevice.getCreateBy()),PrDeviceEntity::getCreateBy,prDevice.getCreateBy());
		wrapper.ge(Objects.nonNull(prDevice.getCreateTime()),PrDeviceEntity::getCreateTime,prDevice.getCreateTime());
		wrapper.eq(StrUtil.isNotBlank(prDevice.getUpdateBy()),PrDeviceEntity::getUpdateBy,prDevice.getUpdateBy());
		Page<PrDeviceEntity> page1 = prDeviceMapper.selectPage(page, wrapper);

		page1.getRecords().forEach(item->{
			//检测在线状态
			if(clientIdList.contains(item.getDevSign())){
				item.setOnline("在线");
				item.setEnabled(Boolean.TRUE);
			}else {
				item.setOnline("离线");
				item.setEnabled(Boolean.FALSE);
			}
		});
		return R.ok(page1);
    }

	/**
	 * 获取在线的设备列表
	 * @return
	 */
	@GetMapping("list")
	public R<List<PrDeviceEntity>> list(){

		EmqxClientQueryDto emqxClientQueryDto = new EmqxClientQueryDto();
		EmqxDataVo<MqttClientStats> mqttClientStats = emqFeignClient.getMqttClientStats(emqxClientQueryDto);
		List<String> clientIdList = mqttClientStats.getData().stream().filter(MqttClientStats::getConnected).map(MqttClientStats::getClientid).collect(Collectors.toList());

		List<PrDeviceEntity> list = prDeviceService.list();
		List<PrDeviceEntity> prDeviceEntityList = list.stream().filter(item ->
				clientIdList.contains(item.getDevSign())).collect(Collectors.toList());

		return R.ok(prDeviceEntityList);
	}

	/**
	 * 分页查询带绑定状态
	 * @param page 分页对象
	 * @param prDevice 设备管理
	 * @return
	 */
	@Operation(summary = "分页查询" , description = "分页查询" )
	@GetMapping("/page/bind" )
	@PreAuthorize("@pms.hasPermission('admin_prDevice_view')" )
	public R getPrDevicePageBind(@ParameterObject Page page, @ParameterObject PrDeviceEntity prDevice) {

		MPJLambdaWrapper<PrDeviceEntity> wrapper = new MPJLambdaWrapper<PrDeviceEntity>().selectAll(PrDeviceEntity.class)
				.selectAll(PrDeviceEntity.class)
				.select(PrDeviceDeptEntity::getDeviceId)
				.select(PrDeviceDeptEntity::getDeptId)
				.selectCollection(PrDeviceDeptEntity.class, PrDeviceEntity::getPrDeviceDeptEntityList)
				.leftJoin(PrDeviceDeptEntity.class,
						on->{on.eq(PrDeviceDeptEntity::getDeviceId, PrDeviceEntity::getId);
							on.eq(null != prDevice.getDeptId(),PrDeviceDeptEntity::getDeptId, prDevice.getDeptId());
							return on;
						});
		if(null != prDevice.getEnabled()) {
			wrapper.eq(prDevice.getEnabled(), PrDeviceDeptEntity::getDeptId, prDevice.getDeptId());
			if(!prDevice.getEnabled()){
				wrapper.isNull(PrDeviceDeptEntity::getDeviceId);
			}
		}
		wrapper.eq(StrUtil.isNotBlank(prDevice.getName()),PrDeviceEntity::getName,prDevice.getName());
		wrapper.eq(StrUtil.isNotBlank(prDevice.getArea()),PrDeviceEntity::getArea,prDevice.getArea());
		wrapper.eq(StrUtil.isNotBlank(prDevice.getDeptName()),PrDeviceEntity::getDeptName,prDevice.getDeptName());
		wrapper.eq(StrUtil.isNotBlank(prDevice.getCreateBy()),PrDeviceEntity::getCreateBy,prDevice.getCreateBy());
		wrapper.ge(Objects.nonNull(prDevice.getCreateTime()),PrDeviceEntity::getCreateTime,prDevice.getCreateTime());
		wrapper.eq(StrUtil.isNotBlank(prDevice.getUpdateBy()),PrDeviceEntity::getUpdateBy,prDevice.getUpdateBy());


		EmqxClientQueryDto emqxClientQueryDto = new EmqxClientQueryDto();
		EmqxDataVo<MqttClientStats> mqttClientStats = emqFeignClient.getMqttClientStats(emqxClientQueryDto);


		return R.ok(prDeviceMapper.selectJoinPage(page,PrDeviceEntity.class, wrapper));
	}



	/**
     * 通过条件查询设备管理
     * @param prDevice 查询条件
     * @return R  对象列表
     */
    @Operation(summary = "通过条件查询" , description = "通过条件查询对象" )
    @GetMapping("/details" )
    @PreAuthorize("@pms.hasPermission('admin_prDevice_view')" )
    public R getDetails(@ParameterObject PrDeviceEntity prDevice) {
        return R.ok(prDeviceService.list(Wrappers.query(prDevice)));
    }

    /**
     * 新增设备管理
     * @param prDevice 设备管理
     * @return R
     */
    @Operation(summary = "新增设备管理" , description = "新增设备管理" )
    @SysLog("新增设备管理" )
    @PostMapping
    @PreAuthorize("@pms.hasPermission('admin_prDevice_add')" )
    public R save(@RequestBody PrDeviceEntity prDevice) {
		try {
			return R.ok(prDeviceService.save(prDevice));
		} catch (Exception e) {
			Throwable rootCause = e;
			while (rootCause.getCause() != null) {
				rootCause = rootCause.getCause();
			}
			if (rootCause instanceof SQLIntegrityConstraintViolationException) {
				return R.failed("设备编号重复");
			}
		}
		return R.failed("添加失败");
	}

	/**
     * 修改设备管理
     * @param prDevice 设备管理
     * @return R
     */
    @Operation(summary = "修改设备管理" , description = "修改设备管理" )
    @SysLog("修改设备管理" )
    @PutMapping
    @PreAuthorize("@pms.hasPermission('admin_prDevice_edit')" )
    public R updateById(@RequestBody PrDeviceEntity prDevice) {
		try {
			return R.ok(prDeviceService.updateById(prDevice));
		} catch (Exception e) {
			Throwable rootCause = e;
			while (rootCause.getCause() != null) {
				rootCause = rootCause.getCause();
			}
			if (rootCause instanceof SQLIntegrityConstraintViolationException) {
				R.failed("设备编号重复");
			}
		}
		return R.failed("添加失败");
	}
	private final PrRfidService prRfidService;
	private final PrUserService prUserService;
	private final PrUserRfidInfoService prUserRfidInfoService;
    /**
     * 通过id删除设备管理
     * @param ids id列表
     * @return R
     */
    @Operation(summary = "通过id删除设备管理" , description = "通过id删除设备管理" )
    @SysLog("通过id删除设备管理" )
    @DeleteMapping
    @PreAuthorize("@pms.hasPermission('admin_prDevice_del')" )
    public R removeById(@RequestBody Long[] ids) {
		List<PrDeviceEntity> prDeviceEntityList = prDeviceService.listByIds(Arrays.asList(ids));
		Set<String> deviceSignList = prDeviceEntityList.stream().map(PrDeviceEntity::getDevSign).collect(Collectors.toSet());

		//删除对应的标签信息
		QueryWrapper<PrRfidEntity> prRfidEntityQueryWrapper = new QueryWrapper<>();
		prRfidEntityQueryWrapper.lambda().in(PrRfidEntity::getDeviceSign, deviceSignList);
		prRfidService.remove(prRfidEntityQueryWrapper);
		//删除柜体用户信息
		QueryWrapper<PrUserEntity> userEntityQueryWrapper = new QueryWrapper<>();
		userEntityQueryWrapper.lambda().in(PrUserEntity::getDeviceSign, deviceSignList);
		prUserService.remove(userEntityQueryWrapper);
		//删除柜体用户与标签绑定的信息
		QueryWrapper<PrUserRfidInfoEntity> userRfidInfoEntityQueryWrapper = new QueryWrapper<>();
		userRfidInfoEntityQueryWrapper.lambda().in(PrUserRfidInfoEntity::getDeviceSign, deviceSignList);
		prUserRfidInfoService.remove(userRfidInfoEntityQueryWrapper);

		//删除柜体信息
		boolean b = prDeviceService.removeBatchByIds(CollUtil.toList(ids));
		return R.ok();
    }


    /**
     * 导出excel 表格
     * @param prDevice 查询条件
   	 * @param ids 导出指定ID
     * @return excel 文件流
     */
    @ResponseExcel
    @GetMapping("/export")
    @PreAuthorize("@pms.hasPermission('admin_prDevice_export')" )
    public List<PrDeviceEntity> exportExcel(PrDeviceEntity prDevice,Integer[] ids) {
        return prDeviceService.list(Wrappers.lambdaQuery(prDevice).in(ArrayUtil.isNotEmpty(ids), PrDeviceEntity::getId, ids));
    }

    /**
     * 导入excel 表
     * @param prDeviceList 对象实体列表
     * @param bindingResult 错误信息列表
     * @return ok fail
     */
    @PostMapping("/import")
    @PreAuthorize("@pms.hasPermission('admin_prDevice_export')" )
    public R importExcel(@RequestExcel List<PrDeviceEntity> prDeviceList, BindingResult bindingResult) {
        return R.ok(prDeviceService.saveBatch(prDeviceList));
    }
	private final MqttMessageSender mqttMessageSender;


	/**
	 * 连接mq 检测心跳
	 * @param devSign
	 * 设备编号
	 * @return
	 */
	@GetMapping("client/mq")
	public R clientMq(@RequestParam String devSign,@RequestParam String name) {

		//客户端是否存在
		List<MqttClientStats> collect = getMqttClientStats(devSign);
		return R.ok(collect.size());
	}
	@GetMapping("send/client")
	public R send(@RequestParam String client){
		CoapClientDto coapClientDto = new CoapClientDto();

		emqFeignClient.coapClients(coapClientDto);
		return R.ok();
	}
	@NotNull
	private List<MqttClientStats> getMqttClientStats(String devSign) {
		EmqxClientQueryDto emqxClientQueryDto = new EmqxClientQueryDto();
		emqxClientQueryDto.setLike_clientid(devSign);
		EmqxDataVo<MqttClientStats> mqttClientStats = emqFeignClient.getMqttClientStats(emqxClientQueryDto);
		List<MqttClientStats> data = mqttClientStats.getData();
		List<MqttClientStats> collect = data.stream().filter(item -> item.getClientid().equals(devSign)).collect(Collectors.toList());
		return collect;
	}
}
